using System;
using System.Collections.Generic;
using System.Diagnostics;
using Godot;

namespace MyCraft2;

public class ChunkTier
{
    private readonly ArrayMesh ArrayMesh;
    private readonly Dictionary<Vector3, Block> Blocks = [];
    private readonly SurfaceTool SurfaceTool;
    private string? SurfaceName;

    public ChunkTier(ArrayMesh arrayMesh)
    {
        ArrayMesh = arrayMesh;
        SurfaceTool = new SurfaceTool();
    }

    public Block? GetBlock(Vector3I position)
    {
        return Blocks.GetValueOrDefault(position);
    }

    public void SetBlock(Vector3 position, Block? block, bool commit = false)
    {
        if (block is null) Blocks.Remove(position);
        else Blocks[position] = block;
        if (commit) Commit();
    }

    public void Commit()
    {
        SurfaceTool.Begin(Mesh.PrimitiveType.Triangles);
        SurfaceTool.SetCustomFormat(0, SurfaceTool.CustomFormat.Rgba8Unorm);
        foreach (var block in Blocks)
        foreach (var indexes in Block.FaceVerticesIndex)
        {
            var db = ChunkManager.GetBlock((Vector3I)(block.Key + indexes.Key));
            if (db is not null) continue;
            foreach (var index in indexes.Value)
            {
                var blockTexture = block.Value.GetTexture(indexes.Key);
                SurfaceTool.SetUV2(new Vector2(blockTexture.Id, 0));
                SurfaceTool.SetUV(GetFaceUv(Block.Vertices[index], indexes.Key));

                SurfaceTool.SetNormal(indexes.Key);
                SurfaceTool.SetColor(blockTexture.AlbedoColor ?? Colors.White);
                SurfaceTool.AddVertex(block.Key + Block.Vertices[index]);
            }
        }

        if (SurfaceName is not null) ArrayMesh.SurfaceRemove(ArrayMesh.SurfaceFindByName(SurfaceName));
        SurfaceTool.Commit(ArrayMesh);
        SurfaceTool.Clear();
        SurfaceName ??= $"SurfaceTool-{ArrayMesh.GetSurfaceCount()}";
        ArrayMesh.SurfaceSetName(ArrayMesh.GetSurfaceCount() - 1, SurfaceName);
    }

    private static Vector2 GetFaceUv(Vector3 localPos, Vector3 direction)
    {
        // 根据实际面朝向计算基础UV
        Vector2 uv;
        if (direction == Vector3.Up || direction == Vector3.Down)
            uv = new Vector2(localPos.X + 0.5f, localPos.Z + 0.5f);
        else if (direction == Vector3.Forward)
            uv = new Vector2(localPos.X + 0.5f, localPos.Y + 0.5f);
        else if (direction == Vector3.Back)
            uv = new Vector2(1 - (localPos.X + 0.5f), localPos.Y + 0.5f);
        else if (direction == Vector3.Left)
            uv = new Vector2(localPos.Z + 0.5f, localPos.Y + 0.5f);
        else if (direction == Vector3.Right)
            uv = new Vector2(1 - (localPos.Z + 0.5f), localPos.Y + 0.5f);
        else
            throw new ArgumentException("Invalid direction");

        // 适配Godot的UV坐标系：翻转V轴
        uv.Y = 1 - uv.Y;
        return uv;
    }
}